package top.lcm889.juc.线程安全问题.model;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Coder-lcm
 * @date 2021/4/10
 */
public class Account {
    private String No;
    private Double balance;
    // 方式2 ： 通过Lock类来实现同步锁
    private Lock lock = new ReentrantLock();

    // 模拟同步的取钱方法
    /**
     * 方式1 ： 通过synchronized关键字来实现
     * @param getMoneyCount
     */
    public synchronized void getMoneyOut(double getMoneyCount) {
        if (balance >= getMoneyCount) {
            // 模拟吐出钞票
            System.out.println(Thread.currentThread().getName() + " 取钱成功！" + getMoneyCount);
            try {
                Thread.sleep(1);
            }catch (Exception e){
                e.printStackTrace();
            }
            //修改余额
            balance -= getMoneyCount;
            System.out.println("\t余额为：" + balance);
        }else {
            System.out.println(Thread.currentThread().getName() + ": 余额不足，取款失败");
        }
    }

    public void getMoneyOutByLock(double getMoneyCount) {
        lock.lock();
        try {
            if (balance >= getMoneyCount) {
                // 模拟吐出钞票
                System.out.println(Thread.currentThread().getName() + " 取钱成功！" + getMoneyCount);
                try {
                    Thread.sleep(1);
                }catch (Exception e){
                    e.printStackTrace();
                }
                //修改余额
                balance -= getMoneyCount;
                System.out.println("\t余额为：" + balance);
            }else {
                System.out.println(Thread.currentThread().getName() + ": 余额不足，取款失败");
            }
        }finally {
            // 与synchronized不同的是，需要手动的释放锁，否则会引起死锁问题
            lock.unlock();
        }

    }

    public Account() {
    }

    public Account(String no, Double balance) {
        No = no;
        this.balance = balance;
    }

    public String getNo() {
        return No;
    }

    public void setNo(String no) {
        No = no;
    }

    public Double getBalance() {
        return balance;
    }

    public void setBalance(Double balance) {
        this.balance = balance;
    }

    @Override
    public int hashCode() {
        return No.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof  Account) {
            Account account = (Account) obj;
            return account.No.equals(No);
        }
        return false;
    }
}
